#include "WktJson.h"
#include <QDebug>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>

namespace bg = boost::geometry;
typedef bg::model::d2::point_xy<double> point_type;

WktJson::WktJson()
{
}

WktJson::~WktJson()
{
}

Feature::Type WktJson::parseWkt(const QString &wkt, CoordinatesCollections &coorsCollections)
{
    Feature::Type fType{Feature::Type::PointType};

    int n = wkt.length();
    int m = wkt.indexOf('(');

    if (0 == n || -1 == m)
        return fType;

    QStringRef stype = wkt.leftRef(m).trimmed();
    if (stype == "POINT")
    {
        fType = Feature::Type::PointType;
        QStringRef scoor = wkt.midRef(m + 1, n - m - 2); // 去掉类型和头尾括号

        QVector<QStringRef> ss = scoor.split(' ', QString::SkipEmptyParts);
        if (ss.count() != 2)
            return fType;
        coorsCollections.append({{Coordinate(ss.last().toDouble(), ss.first().toDouble())}});
    }
    else if (stype == "MULTIPOINT")
    {
        fType = Feature::Type::PointType;
        QStringRef scoor = wkt.midRef(m + 2, n - m - 4); // 去掉类型和头尾括号
        QVector<QStringRef> slist = scoor.split("), (", QString::SkipEmptyParts);
        Coordinates coors;
        foreach (auto &s, slist)
        {
            QVector<QStringRef> ss = scoor.split(' ', QString::SkipEmptyParts);
            if (ss.count() != 2)
                return fType;
            coors.append(Coordinate(ss.last().toDouble(), ss.first().toDouble()));
        }
        coorsCollections.append({coors});
    }
    else if (stype == "LINESTRING")
    {
        fType = Feature::Type::LineStringType;
        QStringRef scoor = wkt.midRef(m + 1, n - m - 2); // 去掉类型和头尾括号
        Coordinates coors;
        parseCoors(scoor, coors);
        coorsCollections.append({coors});
    }
    else if (stype == "MULTILINESTRING")
    {
        fType = Feature::Type::LineStringType;
        QStringRef scoor = wkt.midRef(m + 2, n - m - 4); // 去掉类型和头尾括号
        CoordinatesCollection coorsCollection;
        parsePolygon(scoor, coorsCollection);
        coorsCollections.append(coorsCollection);
    }
    else if (stype == "POLYGON")
    {
        fType = Feature::Type::PolygonType;
        QStringRef scoor = wkt.midRef(m + 2, n - m - 4); // 去掉类型和头尾括号
        CoordinatesCollection coorsCollection;
        parsePolygon(scoor, coorsCollection);
        coorsCollections.append(coorsCollection);
    }
    else if (stype == "MULTIPOLYGON")
    {
        fType = Feature::Type::PolygonType;
        QStringRef scoor = wkt.midRef(m + 3, n - m - 6); // 去掉类型和头尾括号
        parseMutiPolygon(scoor, coorsCollections);
    }

    return fType;
}

bool WktJson::parseWkt(const QString &wkt, Coordinate &coor)
{
    int n = wkt.length();
    int m = wkt.indexOf('(');

    if (0 == n || -1 == m)
        return false;

    QStringRef stype = wkt.leftRef(m).trimmed();
    if (stype == "POINT")
    {
        QStringRef scoor = wkt.midRef(m + 1, n - m - 2); // 去掉类型和头尾括号

        QVector<QStringRef> ss = scoor.split(' ', QString::SkipEmptyParts);
        if (ss.count() != 2)
            return false;
        coor = Coordinate(ss.last().toDouble(), ss.first().toDouble());
        return true;
    }
    return false;
}

void WktJson::parseMutiPolygon(const QStringRef &scoor, CoordinatesCollections &coorsCollections)
{
    QVector<QStringRef> slist = scoor.split(")), ((", QString::SkipEmptyParts);
    foreach (auto &s, slist)
    {
        CoordinatesCollection coorsCollection;
        parsePolygon(s, coorsCollection);
        coorsCollections.append(coorsCollection);
    }
}

void WktJson::parsePolygon(const QStringRef &scoor, CoordinatesCollection &coorsCollection)
{
    QVector<QStringRef> slist = scoor.split("), (", QString::SkipEmptyParts);
    for (int i = 0, n = slist.count(); i < n; i++)
    {
        const QStringRef &s = slist.at(i);
        Coordinates coors;
        parseCoors(s, coors);
        coorsCollection.append({coors});
    }
}

void WktJson::parseCoors(const QStringRef &scoor, Coordinates &coors)
{
    QVector<QStringRef> slist = scoor.split(",", QString::SkipEmptyParts);
    foreach (auto &s, slist)
    {
        QVector<QStringRef> ss = s.split(' ', QString::SkipEmptyParts);
        if (ss.count() != 2)
        {
            qInfo() << "parseCoors==============" << scoor << ss;
            continue;
        }
        coors.append(Coordinate(ss.last().toDouble(), ss.first().toDouble()));
    }
}

QString WktJson::coorToWkt(const Coordinate &coor)
{
    point_type a(coor.second, coor.first);
    return QString::fromStdString(bg::to_wkt(a, 11));
}

Coordinate WktJson::wktToCoor(const QString &wkt)
{
    point_type a;
    try
    {
        bg::read_wkt(wkt.toStdString(), a);
    }
    catch (...)
    {
        return Coordinate(91, 181);
    }
    return Coordinate(a.get<1>(), a.get<0>());
}
